#include "driver_Mobvoi_includes.h"
#include "app_Mobvoi_includes.h"
#include "Mobvoi_external.h"
#include "bt_init.h"
#include "tra_hcit.h"

extern uint32_t XVR_analog_reg_save[16];
static BT_ENTITY_T Remote_BlueDev = {0, {{0}}};
//BT_ENTITY_T dis_dev = {0,{{0}}};
//static int32_t retry_count = 0;
/* api declaration*/
extern t_scanEnable LMscan_Read_Scan_Enable(void);
extern void MOBVOIxvr_Set_Tx_Power(uint32 pwr);
#if A2DP_ROLE_SOURCE_CODE
extern result_t a2dpSrcCmdConnect(char *params, unsigned int len);
extern uint8_t get_a2dp_role(void);
#endif
/*
test scenarios:
    1: '0'
    2: '1'
    3: '1010'
    4: PN9
    5: loopback/acl
    6: loopback/sco
    7: acl/no whiten
    8: sco/no whiten
    9: '11110000'

Packet Type:
    NULLpkt     =  0,
    POLLpkt     =  1,
    FHSpkt      =  2,
    DM1         =  3,
    DH1         =  4,
    HV1         =  5,
    HV2         =  6,
    HV3         =  7,
    DV          =  8,
    AUX1        =  9,
    DM3         = 10,
    DH3         = 11,
    EV4         = 12,
    EV5         = 13,
    DM5         = 14,
    DH5         = 15,
    IDpkt       = 16,
    EDR_2DH1    = 20,
	EV3         = 21,
    EDR_2EV3    = 22,
    EDR_3EV3    = 23,
	EDR_3DH1    = 24,
	EDR_AUX1    = 25,
    EDR_2DH3    = 26,
    EDR_3DH3    = 27,
    EDR_2EV5    = 28,
    EDR_3EV5    = 29,
    EDR_2DH5    = 30,
    EDR_3DH5    = 31
*/
void app_bt_enable_non_signal_test(t_TestControl *tc_contents)
{
    uint8 tc_pdu[17] = {0x00};
    uint16 payload_len = SYSconst_Get_Packet_Length(tc_contents->packet_type);
    if (!(app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE)))
    {
        LOG_E(DUT, "Non-Signal Test must be on DUT mode\r\n");
        return;
    }

    MOBVOIxvr_Set_Tx_Power(tc_contents->tx_power);
    tc_pdu[0] = 0x01;
    tc_pdu[1] = 0x8c;
    tc_pdu[2] = 0xfc;
    tc_pdu[3] = 0x0D;
    tc_pdu[4] = tc_contents->tester_lap_nap & 0xff;
    tc_pdu[5] = (tc_contents->tester_lap_nap >> 8) & 0xff;
    tc_pdu[6] = (tc_contents->tester_lap_nap >> 16) & 0xff;
    tc_pdu[7] = (tc_contents->tester_lap_nap >> 24) & 0xff;
    tc_pdu[8] = tc_contents->test_scenarios ^ 0x55;
    tc_pdu[9] = tc_contents->hop_mode ^ 0x55;
    tc_pdu[10] = tc_contents->tx_chnl ^ 0x55;
    tc_pdu[11] = tc_contents->rx_chnl ^ 0x55;
    tc_pdu[12] = 0x00 ^ 0x55;
    tc_pdu[13] = tc_contents->interval ^ 0x55;
    tc_pdu[14] = tc_contents->packet_type ^ 0x55;
    tc_pdu[15] = (payload_len & 0xff) ^ 0x55;
    tc_pdu[16] = ((payload_len >> 8) & 0x0ff) ^ 0x55;
    uart_send_poll(tc_pdu, sizeof(tc_pdu));
}

int bt_is_reject_new_connect(void)
{
    int ret = 0;

    app_handle_t sys_hdl = app_get_sys_handler();
    int acl_count = hci_get_acl_link_count(sys_hdl->unit);

    if (hfp_has_sco() // app_bt_flag2_get(APP_FLAG2_CALL_PROCESS)
        || (acl_count >= BT_MAX_AG_COUNT))
    {
        LOG_I(CONN, "reject flag2:0x%x,music:%d,acl cnt:%d\r\n", sys_hdl->flag_sm2, a2dp_has_music(), acl_count);
        ret = 1;
    }

    if (app_bt_flag1_get(APP_FLAG_AUTO_CONNECTION | APP_FLAG_RECONNCTION))
    {
        LOG_I(CONN, "reject flag:0x%x\r\n", sys_hdl->flag_sm1);

        ret = 1;
    }

    return ret;
}

void app_bt_enable_complete_wrap(hci_unit_t *unit)
{
    uint32_t i;
    uint8_t cmd[256];
    app_handle_t sys_hdl = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();

    CLEAR_PWDOWN_TICK;
    CLEAR_SLEEP_TICK;
    if (!(app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE)))
    {
        app_bt_flag1_set(APP_BUTTON_FLAG_BT_ENABLE, 1);
        sys_hdl->unit = unit;

        btaddr_copy(&sys_hdl->remote_btaddr, &env_h->env_data.default_btaddr);
    }

    for (i = 0; i < MAX_KEY_STORE; i++)
    {
        if ((env_h->env_data.key_pair[i].used == 0x01) || (env_h->env_data.key_pair[i].used == 0x02))
        {
            memcpy(&cmd[i * 22 + 1], (uint8_t *)&env_h->env_data.key_pair[i].btaddr, 6);
            memcpy(&cmd[i * 22 + 7], (uint8_t *)env_h->env_data.key_pair[i].linkkey, 16);
            if (env_h->env_data.key_pair[i].a2dp_src_uclass)
            {
                int8_t idx = bt_app_entity_find_id_from_raddr(&(env_h->env_data.key_pair[i].btaddr));
                if (idx == MNG_ERROR_NO_ENTITY)
                {
                    LOG_I(ENV, "MNG_ERROR_NO_ENTITY\r\n")
                }
                bt_app_entity_set_mac_win_book(idx, 1);
            }
        }
        else
        {
            //break;
        }
    }

    if (i > MAX_KEY_STORE)
    {
        i = MAX_KEY_STORE;
    }

    if (i > 0)
    {
        cmd[0] = i;
        hci_send_cmd(sys_hdl->unit,
                     HCI_CMD_WRITE_STORED_LINK_KEY,
                     cmd,
                     i * 22 + 1);
    }
    else
    {
        unit->app_cbs.write_linkkey_complete_cb(unit->app_ctx, 0);
    }
}

#if 0
static void app_bt_match_timeout_timerfunc(void *arg)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();

    app_sleep_func(0);

    if((env_h->env_cfg.bt_para.bt_flag & APP_ENV_BT_FLAG_AUTO_CONN_PERIOD)
        && (0 == app_bt_get_disconn_event()))
    {
        if(! (app_bt_flag1_get(APP_FLAG_AUTO_CONNECTION)))
        {
            app_bt_flag1_set(APP_FLAG_AUTO_CONNECTION, 1);
            bt_auto_connect_start();
        }
    }
    else
    {
        bt_unit_set_scan_enable(sys_hdl->unit, HCI_PAGE_SCAN_ENABLE);
        app_set_led_event_action(LED_EVENT_NO_MATCH_NO_CONN_STATE);
    }
}

void app_bt_set_match_timeout(void)
{
    app_env_handle_t env_h = app_env_get_handle();
    app_handle_t sys_hdl = app_get_sys_handler();

    if(env_h->env_cfg.bt_para.match_timeout == -1)
        return;

    jtask_stop(sys_hdl->app_match_task);

    jtask_schedule(sys_hdl->app_match_task,
                    env_h->env_cfg.bt_para.match_timeout*1000,
                    (jthread_func)app_bt_match_timeout_timerfunc,
                    (void *)NULL);
}
#endif

void bt_create_conn_status_wrap(uint8_t status)
{
    LOG_I(CONN, "create_conn_status_wrap,%x\r\n", status);
    if (app_bt_flag1_get(APP_FLAG_AUTO_CONNECTION))
    {
        if (status == 0) // auto connection success
        {
            app_bt_flag1_set(APP_FLAG_ACL_CONNECTION, 1);
        }
        else //auto connection failed
        {

            //            bt_auto_connect_stop();
            if (!app_bt_flag1_get(APP_FLAG_MATCH_ENABLE))
                app_set_led_event_action(LED_EVENT_NO_MATCH_NO_CONN_STATE);
        }
    }
    else if (app_bt_flag1_get(APP_FLAG_RECONNCTION))
    {
        LOG_I(CONN, "create_conn1\r\n");
        if (status == 0)
        {
            app_bt_flag1_set(APP_FLAG_ACL_CONNECTION, 1);
        }
    }
}

void app_bt_disable_complete_wrap(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    LOG_I(APP, "app_bt_disable_complete_wrap()\r\n");

    jtask_stop(sys_hdl->app_match_task);

    app_bt_flag1_set(APP_BUTTON_FLAG_BT_ENABLE, 0);

    if (app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE))
    {
        CONST static char bluecmdDut0[] = {0x01, 0x1A, 0x0c, 0x01, 0x03};
        CONST static char bluecmdDut1[] = {0x01, 0x05, 0x0c, 0x03, 0x02, 0x00, 0x02};
        CONST static char bluecmdDut2[] = {0x01, 0x03, 0x18, 0x00};
        //M510_GPIO_18_CONFIG = 0x40;   // radio on status;
        //M510_GPIO_GPIODCON |= (1<<18);
        uart_send_poll((uint8_t *)bluecmdDut0, sizeof(bluecmdDut0));
        uart_send_poll((uint8_t *)bluecmdDut1, sizeof(bluecmdDut1));
        uart_send_poll((uint8_t *)bluecmdDut2, sizeof(bluecmdDut2));
        LOG_I(APP, "Enter Dut test mode success!\r\n");
        app_set_led_event_action(LED_EVENT_TEST_MODE);
    }
    else if (app_bt_flag1_get(APP_FLAG_POWERDOWN))
    {
        app_set_led_event_action(LED_EVENT_POWER_OFF);
        app_led_action(1);

        if (app_check_bt_mode(BT_MODE_1V1 | BT_MODE_DM_1V1 | BT_MODE_BLE))
        {
            app_bt_shedule_task((jthread_func)app_powerdown_action, (void *)sys_hdl->unit, 500);
        }
        else
        {
            app_bt_shedule_task((jthread_func)app_powerdown_action, (void *)sys_hdl->unit, 1000);
        }
    }
    else if (app_bt_flag1_get(APP_FLAG_LINEIN))
    {
        jtask_stop(sys_hdl->app_auto_con_task);
        app_bt_flag1_set((APP_FLAG_RECONNCTION | APP_FLAG_AUTO_CONNECTION), 0);
        jtask_stop(sys_hdl->app_reset_task);
        sys_hdl->button_mode = BUTTON_NONE;
        sys_hdl->button_commit = BUTTON_NONE;
        sys_hdl->button_press_count = 0;
        sys_hdl->button_long_press_count = 0;
        sys_hdl->button_state = BUTTON_PRESS_NONE;

        M510_Ana_Line_enable(1);
        aud_dac_set_volume(sys_hdl->linein_vol);
        aud_volume_mute(0);
        aud_PAmute_delay_operation(0);

        LOG_I(APP, "linein_vol:%d\r\n", sys_hdl->linein_vol);
    }
}

#if CONFIG_BLUETOOTH_HID
extern void Set_photoKey(void);
#endif
void app_bt_conn_compl_wrap(hci_link_t *link, const btaddr_t *rbtaddr)
{
    app_handle_t sys_hdl = app_get_sys_handler();

#ifndef CONFIG_BLUETOOTH_SSP
    uint32_t a2dp_conn_delay;
    app_env_handle_t env_h = app_env_get_handle();
#endif

    int8_t id = bt_app_entity_find_id_from_raddr((btaddr_t *)rbtaddr);
    if (!bt_app_entity_get_connect_flag(id, BT_CONNECT_STATE_RECONNECTING))
    {
        if (bt_acl_con_get_specific_uclass())
        {
            bt_app_entity_set_mac_win_book(id, 1);
        }
        else
        {
            bt_app_entity_set_mac_win_book(id, 0);
        }
    }
    if (bt_app_entity_get_mac_win_book(id))
        LOG_I(CONN, "A2DP.SRC is mac|win\r\n");

    bt_app_entity_clear_sys_flag(id, SYS_WORK_WAVE_PLAY);
    app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 0);
    jtask_stop(sys_hdl->app_a2dp_task);

    LOG_I(APP, "app_bt_conn_compl_wrap 0\r\n");

#if CONFIG_BLUETOOTH_HID
    if (app_env_check_HID_profile_enable())
        Set_photoKey();
#endif

    CLEAR_PWDOWN_TICK;
    CLEAR_SLEEP_TICK;

    app_bt_flag1_set(APP_FLAG_ACL_CONNECTION, 1);
    memcpy((uint8_t *)&sys_hdl->remote_btaddr,
           (uint8_t *)rbtaddr,
           sizeof(btaddr_t));
    sys_hdl->link_handle = link->hl_handle;

    set_connection_event(&sys_hdl->remote_btaddr, CONN_EVENT_ACL_CONNECTED);

    if (app_bt_flag1_get(APP_FLAG_RECONNCTION) && btaddr_same(rbtaddr, &sys_hdl->reconn_btaddr))
        jtask_stop(sys_hdl->app_auto_con_task);

    jtask_stop(sys_hdl->app_match_task);
    bt_app_entity_clear_bt_connected_wrap(id);
#if CONFIG_CRTL_POWER_IN_BT_SNIFF_MODE
    uint8_t idx = 0;
    idx = bt_sniff_find_st_available();
    if (idx < NEED_SNIFF_DEVICE_COUNT)
        bt_sniff_alloc_st(idx, sys_hdl->link_handle, &sys_hdl->remote_btaddr);
#endif
}

void app_bt_shedule_task(jthread_func func, void *arg, uint32_t delay_ms)
{

    app_handle_t sys_hdl = app_get_sys_handler();

    jtask_stop(sys_hdl->app_auto_con_task);

    if (func == NULL)
        return;

    CLEAR_PWDOWN_TICK;
    CLEAR_SLEEP_TICK;
    jtask_schedule(sys_hdl->app_auto_con_task, delay_ms, func, arg);
}

int app_bt_get_disconn_event(void)
{
    app_env_handle_t env_h = app_env_get_handle();

    return env_h->env_cfg.bt_para.action_disconn;
}

void app_bt_reconn_after_callEnd(void)
{
    return;
}

void app_bt_connected_wrap(btaddr_t *raddr)
{
    int ret;
    uint8_t id = 0;
    MSG_T msg;
    app_env_handle_t env_h = app_env_get_handle();

    memcpy((uint8_t *)&env_h->env_data.default_btaddr, (uint8_t *)raddr, sizeof(btaddr_t));
    env_h->env_data.offset_bak_phone = (system_get_0x4d_reg()) | 0x80;
    ret = app_env_write_action(&(env_h->env_data.default_btaddr), 1);
    id = bt_app_entity_find_id_from_raddr(raddr);

    if (ret)
    {
        msg.id = MSG_ENV_WRITE_ACTION;
        msg.arg = 0x01;
        msg.arg2 = id;
        msg.hdl = 0;
        msg_lush_put(&msg);
    }
    LOG_D(CONN, "all profiles are connected,flash write:%d, id:%d\r\n", ret, id);
    bt_app_entity_clear_connect_flag(id, BT_CONNECT_STATE_RECONNECTING);
    bt_app_entity_set_sys_flag(id, SYS_WORK_WAVE_PLAY);
    bt_app_entity_set_event_by_addr(raddr, SYS_BT_CONNECTED_EVENT);
    app_wave_file_play_start(APP_WAVE_FILE_ID_CONN);
    app_set_led_event_action(LED_EVENT_CONN);
}

void app_bt_disconn_wrap(uint8_t reason, btaddr_t *raddr)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();

    int ret;
    MSG_T msg;

#if CONFIG_CRTL_POWER_IN_BT_SNIFF_MODE
    uint8_t idx = 0;
    idx = bt_sniff_get_index_from_raddr(raddr);
    bt_sniff_free_st(idx);
#endif

    app_set_crystal_calibration(0);

    set_connection_event(raddr, CONN_EVENT_NULL);
    bt_app_entity_clear_conn_flag_by_addr(raddr, BT_CONNECT_STATE_DISCONN_PENDING);
    /* bt_app_management */
    bt_app_entity_free_by_addr(raddr, reason);
    env_h->env_data.disconnect_reason = reason;

    // keep the addr printf for confirm problem
    LOG_I(CONN, "bt_disconn_reason: 0x %x, raddr:" BTADDR_FORMAT "\r\n", reason, BTADDR(raddr));

    if (((!app_bt_flag1_get(APP_FLAG_LINEIN)) && (!app_bt_flag2_get(APP_FLAG2_RECONN_AFTER_DISCONNEC))) && (!app_charge_is_powerdown()) && (!app_bt_flag2_get(APP_FLAG2_ROLE_SWITCH_FAIL)))
    {
        if (bt_app_entity_get_sys_flag(bt_app_entity_find_id_from_raddr(raddr), SYS_WORK_WAVE_PLAY))
        {
            app_wave_file_play_start(APP_WAVE_FILE_ID_DISCONN);
        }
        else
        {
            LOG_I(CONN, "disconn no wave play\r\n");
        }
    }
    else
    {
        LOG_I(CONN, "line:%d,reconn_disconn:%d,chg_pd:%d\r\n", !(!app_bt_flag1_get(APP_FLAG_LINEIN)), !(!app_bt_flag2_get(APP_FLAG2_RECONN_AFTER_DISCONNEC)), !(!app_charge_is_powerdown()));
        app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 0);
    }

    app_bt_flag2_set(APP_FLAG2_VOL_SYNC, 0);
    app_bt_flag2_set(APP_FLAG2_VOL_SYNC_OK, 0);

    /* app_bt_flag1_set(APP_FLAG_GET_REMOTE_ADDR,0); */
#if CONFIG_BLUETOOTH_HID
    app_bt_flag1_set(APP_FLAG_HID_CONNECTION, 0);
#endif
    if (app_check_bt_mode(BT_MODE_1V2))
    {
        memcpy((uint8_t *)&env_h->env_data.default_btaddr, (uint8_t *)raddr, sizeof(btaddr_t));
        ret = app_env_write_action(&(env_h->env_data.default_btaddr), 0);
        if (ret)
        {
            msg.id = MSG_ENV_WRITE_ACTION;
            msg.arg = 0x00;
            msg.hdl = 0;
            msg_lush_put(&msg);
        }
    }

    app_bt_reset_policy_iocap();

    if (app_bt_flag1_get(APP_FLAG_POWERDOWN))
    {
        app_bt_shedule_task((jthread_func)app_powerdown_action, (void *)sys_hdl->unit, 1000);
        LOG_I(CONN, "app_bt_disconn_wrap, Exit 1, 0x%x \r\n", sys_hdl->flag_sm1);
        return;
    }

    if (app_bt_flag2_get(APP_FLAG2_CHARGE_POWERDOWN) && get_Charge_state())
    {
        app_bt_shedule_task((jthread_func)app_set_powerdown_flag, (void *)POWERDOWN_CHG_DEEPSLEEP, 500);
        return;
    }

    if (app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE))
    {
        jtask_stop(sys_hdl->app_reset_task);
        jtask_schedule(sys_hdl->app_reset_task, 1000, (jthread_func)hci_disable_task, (void *)sys_hdl->unit);

        env_h->env_data.offset_bak_8852 = system_get_0x4d_reg() | 0x80;
        app_env_write_action(&env_h->env_data.default_btaddr, 0);

        LOG_I(CONN, "DUT,flag1:0x%x,offset:%d\r\n", sys_hdl->flag_sm1, env_h->env_data.offset_bak_8852);
        return;
    }

    if (!hfp_has_sco())
    {
        app_bt_flag1_set((APP_FLAG_HFP_CALLSETUP), 0);
        app_bt_flag2_set(APP_FLAG2_CALL_PROCESS, 0);
    }
    if (!hci_get_acl_link_count(sys_hdl->unit))
    {
        app_bt_flag1_set(APP_AUDIO_FLAG_SET, 0);
    }

    if (!hci_get_acl_link_count(sys_hdl->unit))
    {
        if (app_env_check_inquiry_always())
        {
            ; //app_set_led_event_action( LED_EVENT_MATCH_STATE );
        }
        else
        {
            if (!app_bt_flag1_get(APP_FLAG_MATCH_ENABLE))
                app_set_led_event_action(LED_EVENT_NO_MATCH_NO_CONN_STATE);
        }
    }
    else
    {
        if (a2dp_has_music())
            app_set_led_event_action(LED_EVENT_BT_PLAY);
        else
            app_set_led_event_action(LED_EVENT_CONN);
    }
}

void app_bt_auto_conn_ok(void)
{
    LOG_I(CONN, "app_bt_auto_conn_ok\r\n");

    app_handle_t sys_hdl = app_get_sys_handler();
    jtask_stop(sys_hdl->app_reset_task);

    if (app_bt_flag1_get(APP_FLAG_AUTO_CONNECTION | APP_FLAG_RECONNCTION))
    {
        if (hfp_has_sco())
        {
            app_bt_flag1_set(APP_FLAG_HFP_CALLSETUP, 1);
        }
        if (a2dp_has_connection())
        {
            app_wave_file_play_start(APP_WAVE_FILE_ID_CONN);
        }
        app_bt_flag1_set((APP_FLAG_AUTO_CONNECTION | APP_FLAG_RECONNCTION), 0);
    }

    app_bt_reset_policy_iocap();
    app_linein_state_switch_complete();
}
void a2dp_time_out_to_scan(btaddr_t *rtaddr)
{
    uint32_t id = bt_app_entity_find_id_from_raddr(rtaddr);
    if (!bt_app_entity_get_bt_connected_wrap(id))
    {
        bt_app_entity_set_bt_connected_wrap(id);
        app_bt_connected_wrap(rtaddr);
        bt_app_entity_set_event_by_addr(rtaddr, SYS_BT_CONNECTED_EVENT);
    }
}
//extern uint32_t avrcp_has_the_connection(btaddr_t);
extern void LSLC_crystal_calibration_set(uint8_t calib);
void app_bt_profile_conn_wrap(uint8_t profileId, btaddr_t *rtaddr)
{

    app_handle_t sys_hdl = app_get_sys_handler();

    CLEAR_PWDOWN_TICK;
    CLEAR_SLEEP_TICK;

    if (app_linein_get_state() == LINEIN_W4_ATTACH)
    {
        LOG_D(LINE, "Linein attach, disconnect BT\r\n");
        bt_all_acl_disconnect(sys_hdl->unit);
        return;
    }

    switch (profileId)
    {
    case PROFILE_BT_HFP:
        set_connection_event(rtaddr, CONN_EVENT_HFP_CONNECTED);
        bt_app_entity_set_conn_flag_by_addr(rtaddr, PROFILE_BT_HFP);
        // clear the bat_lever  backup
        sys_hdl->iphone_bat_lever = 0;
        sys_hdl->iphone_bat_lever_bak = -1;
        //sys_hdl->iphone_bat_lever_bak_cnt = 0;
        if (!hfp_has_the_connection(*rtaddr))
            LOG_W(CONN, "Error flag at HFP\r\n");
        break;
    case PROFILE_BT_A2DP_SNK:
        set_connection_event(rtaddr, CONN_EVENT_SNK_A2DP_CONNECTED);
        bt_app_entity_set_conn_flag_by_addr(rtaddr, PROFILE_BT_A2DP_SNK);
        if (!a2dp_has_the_connection(rtaddr))
            LOG_W(CONN, "Error flag at A2DP\r\n");
        if (app_get_best_offset_level() <= 1)
        {
            if (!app_bt_flag2_get(APP_FLAG2_STEREO_WORK_MODE) && app_bt_flag1_get(APP_FLAG_AUTO_CONNECTION))
            {
                LSLC_crystal_calibration_set(0);
            }
        }
        break;
    case PROFILE_BT_AVRCP:
        set_connection_event(rtaddr, CONN_EVENT_AVRCP_CONNECTED);
        bt_app_entity_set_conn_flag_by_addr(rtaddr, PROFILE_BT_AVRCP);
        if (!avrcp_has_the_connection(*rtaddr))
            LOG_W(CONN, "Error flag at AVRCP\r\n");
        break;
#ifdef CONFIG_BLUETOOTH_A2DP_SOURCE
    case PROFILE_BT_A2DP_SRC:
        break;
#endif
#ifdef CONFIG_BLUETOOTH_AGHFP
    case PROFILE_BT_AGHFP:
        break;
#endif
    default:
        break;
    }

#if (CONFIG_AS_SLAVE_ROLE == 0)
    uint8_t role;
    app_bt_flag2_set(APP_FLAG2_ROLE_SWITCH_FAIL, 0);
    role = hci_get_acl_link_role(sys_hdl->unit, rtaddr);
    if (role == HCI_ROLE_SLAVE) // self slave
    {
        LOG_I(ROLE, "role slave,disconnected\r\n");
        app_bt_flag2_set(APP_FLAG2_ROLE_SWITCH_FAIL, 1);
        bt_app_entity_set_event_by_addr(rtaddr, SYS_BT_DISCONN_CONN_EVENT);
        bt_app_disconnect_acl_link_by_raddr(rtaddr);
        return;
    }
#else
    Judge_role(rtaddr, TRUE);
#endif
    uint8_t idx = bt_app_entity_find_id_from_raddr(rtaddr);

    if (a2dp_has_the_connection(rtaddr) && hfp_has_the_connection(*rtaddr) && (!avrcp_has_the_connection(*rtaddr)))
    {
        jtask_schedule(sys_hdl->app_only_a2dp_hfp_link_to_scan_task, 2000, (jthread_func)a2dp_time_out_to_scan, rtaddr);
    }
    if (a2dp_has_the_connection(rtaddr) && avrcp_has_the_connection(*rtaddr) && (!hfp_has_the_connection(*rtaddr)))
    {
        jtask_schedule(sys_hdl->app_only_a2dp_hfp_link_to_scan_task, 2000, (jthread_func)a2dp_time_out_to_scan, rtaddr);
    }
    if (a2dp_has_the_connection(rtaddr) && hfp_has_the_connection(*rtaddr) && avrcp_has_the_connection(*rtaddr))
    {
        if (!bt_app_entity_get_bt_connected_wrap(idx))
        {
            jtask_stop(sys_hdl->app_only_a2dp_hfp_link_to_scan_task);
            app_bt_connected_wrap(rtaddr);
            bt_app_entity_set_event_by_addr(rtaddr, SYS_BT_CONNECTED_EVENT);
            bt_app_entity_set_bt_connected_wrap(idx);
        }

#if SDP_PNP_QUERY_ENABLE
        app_env_handle_t env_h = app_env_get_handle();
        extern uint8_t get_pnp_info(btaddr_t * rtaddr);
        if (get_pnp_info(rtaddr) == 0)
        {
            sdp_connect(&env_h->env_cfg.bt_para.device_addr, rtaddr);
        }
#endif
    }
}

void app_bt_profile_disconn_wrap(uint8_t profileId, void *app_ptr)
{
}

void app_bt_get_remote_addr(btaddr_t *addr)
{
    app_handle_t sys_hdl = app_get_sys_handler();

    btaddr_copy(addr, &sys_hdl->remote_btaddr);
}

void *app_bt_get_handle(uint8_t handle_type)
{
    void *param;
    app_handle_t sys_hdl;

    param = NULL;
    sys_hdl = app_get_sys_handler();
    switch (handle_type)
    {
    case 0:
        param = (void *)sys_hdl->unit;
        break;

    default:
        break;
    }

    //os_printf("%s, sys_hdl->stereo_btaddr: "BTADDR_FORMAT"\r\n", __func__, BTADDR(&sys_hdl->stereo_btaddr));
    return param;
}

void app_bt_reset_policy_iocap(void)
{
#if (CONFIG_AS_SLAVE_ROLE == 0)
    app_handle_t sys_hdl = app_get_sys_handler();

    sys_hdl->unit->hci_link_policy &= ~HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
#endif
#ifdef CONFIG_BLUETOOTH_SSP
    //    if(!app_bt_flag1_get(APP_FLAG_DEBUG_FLAG2))
    {
        bt_sec_set_io_caps(HCI_IO_CAPABILITY_NO_IO);
    }
#endif
}

void app_bt_acl_time_out_wrap(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();

    LOG_I(APP, "app_bt_acl_time_out_wrap\r\n");
    if (sys_hdl->unit != NULL)
    {
        app_bt_flag1_set(APP_AUDIO_FLAG_SET, 0);
        jtask_stop(sys_hdl->app_auto_con_task);
        jtask_stop(sys_hdl->app_reset_task);
        //M510_stop_wdt();
        //aud_volume_mute(1);
        bt_unit_disable(sys_hdl->unit);
        hci_disable_task(sys_hdl->unit);

        Delay(100);
        app_reset();
        app_bt_flag1_set(APP_FLAG_RECONNCTION | APP_FLAG_AUTO_CONNECTION, 1);
    }
}

int app_is_conn_be_accepted(void)
{
    int ret;

    if (app_bt_flag1_get(APP_SDP_DISABLE_FLAG_SET))
    {
        ret = -1;
    }
    else
    {
        ret = 0;
    }

    return ret;
}

result_t app_bt_active_conn_profile(uint8_t profileId, void *arg)
{
    char cmd[40];
    app_handle_t sys_hdl = app_get_sys_handler();

#ifdef CONFIG_BLUETOOTH_HFP
    app_env_handle_t env_h = app_env_get_handle();
#endif

    btaddr_t *remote_btaddr = (btaddr_t *)arg;

    if (sys_hdl->unit == NULL)
    {
        return UWE_NODEV;
    }

    if (NULL == remote_btaddr)
    {
        remote_btaddr = &sys_hdl->remote_btaddr;
    }

    memset(cmd, 0, 40);
    sprintf(cmd, "%u " BTADDR_FORMAT,
            0,
            remote_btaddr->b[5],
            remote_btaddr->b[4],
            remote_btaddr->b[3],
            remote_btaddr->b[2],
            remote_btaddr->b[1],
            remote_btaddr->b[0]);

    LOG_I(CONN, "active:" BTADDR_FORMAT ",profileId:%d\r\n", BTADDR(remote_btaddr), profileId);

#if A2DP_ROLE_SOURCE_CODE
    if (profileId == PROFILE_ID_A2DP)
    {
        if (get_a2dp_role() == A2DP_ROLE_AS_SRC)
            return a2dpSrcCmdConnect(cmd, sizeof(cmd));
        else if (get_a2dp_role() == A2DP_ROLE_AS_SNK)
            return a2dp_cmd_connect(cmd, sizeof(cmd));
    }

#else

#ifdef CONFIG_BLUETOOTH_A2DP
    if (profileId == PROFILE_ID_A2DP)
    {
        return a2dp_cmd_connect(cmd, sizeof(cmd));
    }

    else
#endif

#endif

#ifdef CONFIG_BLUETOOTH_AVRCP
    if (profileId == PROFILE_ID_AVRCP)
        return avrcp_cmd_connect(cmd, sizeof(cmd));
    else
#endif

/*temp assign channel to test, may add sdp sender to get channel for connection sooner*/
#ifdef CONFIG_BLUETOOTH_HFP
        if (profileId == PROFILE_ID_HFP)
    {
        extern uint32_t hfp_is_connecting_based_on_raddr(btaddr_t *);
        if (hfp_is_connecting_based_on_raddr(remote_btaddr))
        {
            LOG_I(CONN, "hfp exit1\r\n");
            return UWE_ALREADY;
        }

        return sdp_connect(&env_h->env_cfg.bt_para.device_addr, remote_btaddr);
    }
    else
#endif

#ifdef CONFIG_BLUETOOTH_HSP
        if (profileId == PROFILE_ID_HSP)
    {
        uint32_t channel = (uint32_t)arg;

        if (channel == 0)
            channel = sys_hdl->hfp_rfcomm_channel - 1;
        //        remote_btaddr = &sys_hdl->remote_btaddr;

        memset(cmd, 0, 40);
        sprintf(cmd, "%u " BTADDR_FORMAT " %u", 0, remote_btaddr->b[5],
                remote_btaddr->b[4], remote_btaddr->b[3],
                remote_btaddr->b[2], remote_btaddr->b[1],
                remote_btaddr->b[0], (unsigned int)channel);
        return hs_cmd_connect(cmd, sizeof(cmd));
    }
    else
#endif

#if CONFIG_BLUETOOTH_HID
        if ((profileId == PROFILE_ID_HID) && app_env_check_HID_profile_enable())
    {
        return hid_cmd_connect(cmd, sizeof(cmd));
    }
    else
#endif
        return 0;
}

void app_bt_key_store_wrap(btaddr_t *raddr, uint8_t *key, uint8_t key_type)
{
    CLEAR_PWDOWN_TICK;
    CLEAR_SLEEP_TICK;
    if (key_type <= 0x06) // HCI_LINK_KEY_TYPE_CHANGED_COMBINATION_KEY=6,combination key type used for standard pairing
    {
        app_env_store_autoconn_info(raddr, key);
    }
}

int app_is_not_powerdown(void)
{
    return !(app_bt_flag1_get(APP_FLAG_POWERDOWN));
}

#if (CONFIG_AS_SLAVE_ROLE == 1)
extern void hci_cmd_role_switch(uint8_t role, btaddr_t *raddr);

uint8_t Judge_role(btaddr_t *btaddr, BOOL connecting)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    uint8_t role;
    btaddr_t *bt_rmtaddr = NULL;
    uint8_t times = 0;

    if (btaddr == NULL)
    {
        bt_rmtaddr = hci_find_acl_slave_link(sys_hdl->unit);
        if ((bt_rmtaddr != NULL) && connecting)
        {
            LOG_I(ROLE, "NoAddr,disconn_reconn\r\n");
            bt_app_entity_set_event_by_addr(bt_rmtaddr, SYS_BT_DISCONN_CONN_EVENT);
            bt_app_disconnect_acl_link_by_raddr(bt_rmtaddr);
            app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
            return 0;
        }
    }
    role = hci_get_acl_link_role(sys_hdl->unit, btaddr);
    if (!app_check_bt_mode(BT_MODE_1V2)) // not 1v2 config
    {
        if (!app_check_bt_mode(BT_MODE_1V1))
        {
            if (role == HCI_ROLE_MASTER) // master
            {
                LOG_I(ROLE, "1V1==rmt addr:%x," BTADDR_FORMAT "\r\n", BTADDR(btaddr));
                times = bt_app_entity_get_role_switch_times_from_raddr(btaddr);
                if (times > 3)
                {
                    bt_app_entity_set_event_by_addr(btaddr, SYS_BT_DISCONN_CONN_EVENT);
                    bt_app_disconnect_acl_link_by_raddr(btaddr);
                    app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
                    return 0;
                }
                hci_cmd_role_switch(HCI_ROLE_SLAVE, btaddr);
                bt_app_entity_set_role_switch_times_from_raddr(btaddr, times + 1);
            }
        }
        return 0;
    }
    else // 1v2 config
    {
        if (hci_get_acl_link_count(sys_hdl->unit) > 1) // have two links;
        {
#if 0
            if((role == HCI_ROLE_SLAVE) && connecting) // slave role, disconnect this link and re-connect;
            {
                LOG_I(ROLE,"1V2,disconn_reconn\r\n");
                bt_app_entity_set_event_by_addr(btaddr,SYS_BT_DISCONN_CONN_EVENT);
                bt_app_disconnect_acl_link_by_raddr(btaddr);
                app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
                /*
                if(app_check_bt_mode(BT_MODE_1V1))
                {
                	app_env_handle_t  env_h = app_env_get_handle();
                	btaddr_copy(&env_h->env_data.default_btaddr,&sys_hdl->remote_btaddr);
                	MSG_T msg;
                	msg.id = MSG_ENV_WRITE_ACTION;
                	msg.arg = 0x01;
                	msg.hdl = 0;
                	msg_lush_put(&msg);
                }*/
                return 1;
            }
            else        // check all links, once has one's link is slave role, then send hci cmd role swtich;
            {
                bt_rmtaddr = hci_find_acl_slave_link(sys_hdl->unit);
                if(bt_rmtaddr != NULL)
                {
                    // hci cmd role switch;
                    LOG_I(ROLE,"===rmt addr:%x,"BTADDR_FORMAT"\r\n", BTADDR(bt_rmtaddr));
                    times = bt_app_entity_get_role_switch_times_from_raddr(bt_rmtaddr);
                    if(times>3)
                    {
                        bt_app_entity_set_event_by_addr(bt_rmtaddr,SYS_BT_DISCONN_CONN_EVENT);
                        bt_app_disconnect_acl_link_by_raddr(bt_rmtaddr);
                        app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
                        return 0;
                    }
                    hci_cmd_role_switch(HCI_ROLE_MASTER,bt_rmtaddr);
                    bt_app_entity_set_role_switch_times_from_raddr(bt_rmtaddr,times+1);
                }
                return 0;
            }
#else
            bt_rmtaddr = hci_find_acl_slave_link(sys_hdl->unit);

            if ((bt_rmtaddr != NULL) && connecting)
            {
                LOG_I(ROLE, "disconn_reconn\r\n");
                bt_app_entity_set_event_by_addr(bt_rmtaddr, SYS_BT_DISCONN_CONN_EVENT);
                bt_app_disconnect_acl_link_by_raddr(bt_rmtaddr);
                app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
            }
            return 0;
#endif
        }
        else // only one link;
        {
#if 0
            if(role == HCI_ROLE_MASTER) // master
            {
                LOG_I(ROLE,"~~~rmt addr:%x,"BTADDR_FORMAT"\r\n", BTADDR(btaddr));
                times = bt_app_entity_get_role_switch_times_from_raddr(btaddr);
                if(times>3)
                {
                    bt_app_entity_set_event_by_addr(btaddr,SYS_BT_DISCONN_CONN_EVENT);
                    bt_app_disconnect_acl_link_by_raddr(btaddr);
                    app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
                    return 0;
                }
                hci_cmd_role_switch(HCI_ROLE_SLAVE,btaddr);
                bt_app_entity_set_role_switch_times_from_raddr(btaddr,times+1);
            }
#endif
            return 0;
        }
    }
}
#endif
#if (CONFIG_AS_SLAVE_ROLE == 0)
//uint8_t Judge_role(void)
uint8_t Judge_role(btaddr_t *btaddr, BOOL connecting)
{
    return 0;
    if (1 == Remote_BlueDev.init_flag)
    {
        app_handle_t sys_hdl = app_get_sys_handler();
        LOG_I(ROLE, "=======Judge_role:%x========\r\n", Remote_BlueDev.init_flag);
        bt_unit_acl_disconnect(sys_hdl->unit, &(Remote_BlueDev.btaddr_def));
        app_bt_flag2_set(APP_FLAG2_RECONN_AFTER_DISCONNEC, 1);
        if (app_check_bt_mode(BT_MODE_1V1))
        {
            app_env_handle_t env_h = app_env_get_handle();
            btaddr_copy(&env_h->env_data.default_btaddr, &sys_hdl->remote_btaddr);
            MSG_T msg;
            msg.id = MSG_ENV_WRITE_ACTION;
            msg.arg = 0x01;
            msg.hdl = 0;
            msg_lush_put(&msg);
        }
        return 1;
    }
    return 0;
}
#endif

void Set_remoteDev_role_btaddr(btaddr_t *btaddr, uint32_t role)
{
    memcpy((uint8_t *)&(Remote_BlueDev.btaddr_def), (uint8_t *)btaddr, sizeof(btaddr_t));
    Remote_BlueDev.init_flag = role;
    LOG_I(ROLE, "===set remote devaddr role:role=%x=====\r\n", Remote_BlueDev.init_flag);
}

void bt_all_acl_disconnect(hci_unit_t *unit)
{
    btaddr_t *raddr[2];
    int i, count = 0;
    count = hci_get_acl_link_addr(unit, raddr);
    for (i = 0; i < count; i++)
    {
        bt_unit_acl_disconnect(unit, (const btaddr_t *)raddr[i]);
        Delay(100);
    }
}

void bt_exchange_hf_active_by_handle(uint16_t handle)
{
    uint8_t tc_cmd[7] = {0x01, 0xe0, 0xfc, 0x03, 0x84, 0x00, 0x00};
    tc_cmd[5] = (uint8_t)(handle & 0xff);
    tc_cmd[6] = (uint8_t)((handle >> 8) & 0xff);
    uart_send_poll(tc_cmd, sizeof(tc_cmd));
}

#if (CONFIG_A2DP_PLAYING_SET_AG_FLOW == 1)
/* Link flow clrl by handle,where:
 * <flow_ctrl> = 0: no flow control;
 * <flow_ctrl> = 1(bit0): Controller flow control,saved air bandwith;
 * <flow_ctrl> = 2(bit1): Host layer flow control,saved sbc node buffer;
 */
void bt_set_ag_flow_ctrl_by_handle(hci_link_t *link)
{
    uint8_t tc_cmd[8] = {0x01, 0xe0, 0xfc, 0x04, 0x83, 0x00, 0x00, 0x01};
    tc_cmd[5] = (uint8_t)(link->hl_handle & 0xff);
    tc_cmd[6] = (uint8_t)((link->hl_handle >> 8) & 0xff);
    tc_cmd[7] = (link->flow_ctrl & 0x03);
    uart_send_poll(tc_cmd, sizeof(tc_cmd));
    jtask_schedule(link->hl_expire, 500, bt_set_ag_flow_ctrl_timeout, link);
}
void bt_set_ag_flow_ctrl_timeout(void *arg)
{
    hci_link_t *link = (hci_link_t *)arg;
    bt_set_ag_flow_ctrl_by_handle(link);
}
#endif

void app_bt_pinkey_missing(btaddr_t *addr)
{
    app_env_handle_t env_h = app_env_get_handle();
    LOG_I(APP, "pin or key missing!Won't reconnect again!\r\n");
    app_env_keypair_used_delete(addr);
    memcpy((uint8_t *)&env_h->env_data.default_btaddr, (uint8_t *)addr, sizeof(btaddr_t));
    MSG_T msg;
    if (!bt_connection_active())
    {
        int ret = 0;
        ret = app_env_write_action(&(env_h->env_data.default_btaddr), 2); // 2 means write flash whatever
        if (ret)
        {
            msg.id = MSG_ENV_WRITE_ACTION;
            msg.arg = 0x00;
            msg.hdl = 0;
            msg_lush_put(&msg);
        }
    }
}

void enter_match_state(void)
{
    app_button_match_action();
}

uint8_t app_set_role_accept_con_req(hci_unit_t *unit, const btaddr_t *btaddr)
{
#if (CONFIG_AS_SLAVE_ROLE == 1)
    {
        app_handle_t sys_hdl = app_get_sys_handler();
        if (!app_check_bt_mode(BT_MODE_1V2))
            return HCI_ROLE_SLAVE;
        else
        {
            if (hci_get_acl_link_count(sys_hdl->unit) < 1)
                return HCI_ROLE_SLAVE;
            else
                return HCI_ROLE_MASTER;
        }
    }
#endif
#if (CONFIG_AS_SLAVE_ROLE == 0)
    if (app_check_bt_mode(BT_MODE_TWS | BT_MODE_DM_TWS))
    {
        if (btaddr_same(btaddr, app_bt_get_handle(2)))
        {
            return HCI_ROLE_SLAVE;
        }
        else
            return HCI_ROLE_MASTER;
    }
    ///else if(app_check_bt_mode(BT_MODE_1V2|BT_MODE_1V1)&&(BT_ONE2MULTIPLE_AS_SCATTERNET == 0))
    else if (app_check_bt_mode(BT_MODE_1V2))
    {
        return HCI_ROLE_MASTER; // HCI_ROLE_MASTER;
    }
    else if (app_check_bt_mode(BT_MODE_1V1))
    {
        if (app_env_check_Use_ext_PA())
        {
            if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
                return HCI_ROLE_MASTER;
            else
                return HCI_ROLE_SLAVE;
        }
        else
        {
#if (BT_ONE2MULTIPLE_AS_SCATTERNET == 0)
            return HCI_ROLE_MASTER; // HCI_ROLE_MASTER;
#else
            if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
                return HCI_ROLE_MASTER;
            else
                return HCI_ROLE_SLAVE;
#endif
        }
    }
    else
    {
        if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
            return HCI_ROLE_MASTER;
        else
            return HCI_ROLE_SLAVE;
    }
#endif
}
// 1=accept_role_switch;
uint8_t app_set_role_creat_con_req(hci_unit_t *unit, const btaddr_t *btaddr)
{
#if (CONFIG_AS_SLAVE_ROLE == 1)
    {
        app_handle_t sys_hdl = app_get_sys_handler();
        if (!app_check_bt_mode(BT_MODE_1V2))
            return 1;
        else
        {
            if (hci_get_acl_link_count(sys_hdl->unit) < 1)
                return 1;
            else
                return 0;
        }
    }
#endif
#if (CONFIG_AS_SLAVE_ROLE == 0)
    if (app_check_bt_mode(BT_MODE_1V2))
    {
        return 0;
    }
    else if (app_check_bt_mode(BT_MODE_1V1))
    {
        if (app_env_check_Use_ext_PA())
        {
            return (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) ? 1 : 0;
        }
        else
        {
#if (BT_ONE2MULTIPLE_AS_SCATTERNET == 0)
            return 0;
#else
            return (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) ? 1 : 0;
#endif
        }
    }
    else
        return (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) ? 1 : 0;
#endif
}
uint8_t app_get_as_slave_role(void)
{
#if (CONFIG_AS_SLAVE_ROLE == 1)
    return 1;
#else
    return 0;
#endif
}
void app_bt_confail_reset_sacn(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    LOG_I(CONN, "reset.sacn:%d\r\n", hci_get_acl_link_count(sys_hdl->unit));
    if (app_check_bt_mode(BT_MODE_1V2))
    {
        if (hci_get_acl_link_count(sys_hdl->unit) < 2)
        {
            bt_unit_set_scan_enable(app_bt_get_handle(0), HCI_PAGE_SCAN_ENABLE | HCI_INQUIRY_SCAN_ENABLE);
        }
    }
}

uint8_t app_bt_a2dp_sbc_default_bitpool(void)
{
    return 53;
}

uint8_t app_bt_rmt_device_type_get(uint8_t id)
{
    uint8_t mac_win_book = 0;
    btaddr_t *addr = bt_app_entit_get_rmt_addr(id);

    if (id == 0xff)
        return BT_DEVICE_NONE;

    mac_win_book = bt_app_entity_get_mac_win_book(id);
    if (mac_win_book)
        return BT_DEVICE_COMPUTER;

    if (a2dp_has_the_connection(addr) && hfp_has_the_connection(*addr) && avrcp_has_the_connection(*addr))
        return BT_DEVICE_PHONE;
    else if (a2dp_has_the_connection(addr) && !hfp_has_the_connection(*addr) && !avrcp_has_the_connection(*addr))
        return BT_DEVICE_TV;
    else
        return BT_DEVICE_OTHER;
}

//EOF
